--- /dev/null
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
+
+const Gdm = imports.gi.Gdm;
+const GLib = imports.gi.GLib;
+const Gtk = imports.gi.Gtk;
+const Lang = imports.lang;
+const Shell = imports.gi.Shell;
+const St = imports.gi.St;
+const Signals = imports.signals;
+const Gettext = imports.gettext.domain('gnome-shell');
+const _ = Gettext.gettext;
+
+const Panel = imports.ui.panel;
+
+// Adapted from gdm/gui/user-switch-applet/applet.c
+//
+// Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
+// Copyright (C) 2008,2009 Red Hat, Inc.
+
+const SIDEBAR_VISIBLE_KEY = 'sidebar/visible';
+
+function StatusMenu() {
+ this._init();
+}
+
+StatusMenu.prototype = {
+ _init: function() {
+ this._gdm = Gdm.UserManager.ref_default();
+ this._user = this._gdm.get_user(GLib.get_user_name());
+
+ this.actor = new St.BoxLayout({ name: 'StatusMenu' });
+ this.actor.connect('destroy', Lang.bind(this, this._onDestroy));
+
+ this._name = new St.Label({ text: this._user.get_real_name() });
+ this.actor.add(this._name, { expand: true, y_align: St.Align.MIDDLE });
+ this._userNameChangedId = this._user.connect('notify::display-name', Lang.bind(this, this._updateUserName));
+
+ this._createSubMenu();
+ this._gdm.connect('users-loaded', Lang.bind(this, this._updateSwitchUser));
+ this._gdm.connect('user-added', Lang.bind(this, this._updateSwitchUser));
+ this._gdm.connect('user-removed', Lang.bind(this, this._updateSwitchUser));
+ },
+
+ _onDestroy: function() {
+ this._user.disconnect(this._userNameChangedId);
+ },
+
+ _updateUserName: function() {
+ this._name.set_text(this._user.get_real_name());
+ },
+
+ _updateSwitchUser: function() {
+ let users = this._gdm.list_users();
+ if (users.length > 1)
+ this._loginScreenItem.show();
+ else
+ this._loginScreenItem.hide();
+ },
+
+ // The menu
+
+ _createImageMenuItem: function(label, iconName) {
+ let image = new Gtk.Image();
+ let item = new Gtk.ImageMenuItem({ label: label,
+ image: image });
+ item.connect('style-set', Lang.bind(this,
+ function() {
+ image.set_from_icon_name(iconName, Gtk.IconSize.MENU);
+ }));
+
+ return item;
+ },
+
+ _createSubMenu: function() {
+ this._menu = new Gtk.Menu();
+ this._menu.connect('deactivate', Lang.bind(this, function() { this.emit('deactivated'); }));
+
+ let item;
+
+ item = this._createImageMenuItem(_('Account Information...'), 'user-info');
+ item.connect('activate', Lang.bind(this, this._onAccountInformationActivate));
+ this._menu.append(item);
+ item.show();
+
+ let gconf = Shell.GConf.get_default();
+ item = new Gtk.CheckMenuItem({ label: _('Sidebar'),
+ active: gconf.get_boolean(SIDEBAR_VISIBLE_KEY) });
+ item.connect('activate', Lang.bind(this,
+ function() {
+ gconf.set_boolean(SIDEBAR_VISIBLE_KEY, this._sidebarItem.active);
+ }));
+ this._menu.append(item);
+ item.show();
+
+ item = this._createImageMenuItem(_('System Preferences...'), 'preferences-desktop');
+ item.connect('activate', Lang.bind(this, this._onPreferencesActivate));
+ this._menu.append(item);
+ item.show();
+
+ item = new Gtk.SeparatorMenuItem();
+ this._menu.append(item);
+ item.show();
+
+ item = this._createImageMenuItem(_('Lock Screen'), 'system-lock-screen');
+ item.connect('activate', Lang.bind(this, this._onLockScreenActivate));
+ this._menu.append(item);
+ item.show();
+
+ item = this._createImageMenuItem(_('Switch User'), 'system-users');
+ item.connect('activate', Lang.bind(this, this._onLoginScreenActivate));
+ this._menu.append(item);
+ item.show();
+ this._loginScreenItem = item;
+
+ item = this._createImageMenuItem(_('Log Out...'), 'system-log-out');
+ item.connect('activate', Lang.bind(this, this._onQuitSessionActivate));
+ this._menu.append(item);
+ item.show();
+
+ item = this._createImageMenuItem(_('Shut Down...'), 'system-shutdown');
+ item.connect('activate', Lang.bind(this, this._onShutDownActivate));
+ this._menu.append(item);
+ item.show();
+ },
+
+ _onAccountInformationActivate: function() {
+ this._spawn(['gnome-about-me']);
+ },
+
+ _onPreferencesActivate: function() {
+ this._spawn(['gnome-control-center']);
+ },
+
+ _onLockScreenActivate: function() {
+ this._spawn(['gnome-screensaver-command', '--lock']);
+ },
+
+ _onLoginScreenActivate: function() {
+ this._gdm.goto_login_session();
+ this._onLockScreenActivate();
+ },
+
+ _onQuitSessionActivate: function() {
+ this._spawn(['gnome-session-save', '--logout-dialog']);
+ },
+
+ _onShutDownActivate: function() {
+ this._spawn(['gnome-session-save', '--shutdown-dialog']);
+ },
+
+ _spawn: function(args) {
+ // FIXME: once Shell.Process gets support for signalling
+ // errors we should pop up an error dialog or something here
+ // on failure
+ let p = new Shell.Process({'args' : args});
+ p.run();
+ },
+
+ // shell_status_menu_toggle:
+ // @event: event causing the toggle
+ //
+ // If the menu is not currently up, pops it up. Otherwise, hides it.
+ // Popping up may fail if another grab is already active; check with
+ // isActive().
+ toggle: function(event) {
+ if (this._menu.visible)
+ this._menu.popdown();
+ else {
+ // We don't want to overgrab a Mutter grab with the grab
+ // that GTK+ uses on menus.
+ if (global.display_is_grabbed())
+ return;
+
+ let [menuWidth, menuHeight] = this._menu.get_size_request ();
+
+ let panel;
+ for (panel = this.actor; panel; panel = panel.get_parent()) {
+ if (panel._delegate instanceof Panel.Panel)
+ break;
+ }
+
+ let [panelX, panelY] = panel.get_transformed_position();
+ let [panelWidth, panelHeight] = panel.get_transformed_size();
+
+ let menuX = Math.round(panelX + panelWidth - menuWidth);
+ let menuY = Math.round(panelY + panelHeight);
+
+ Shell.popup_menu(this._menu, event.get_button(), event.get_time(),
+ menuX, menuY);
+ }
+ },
+
+ // isActive:
+ //
+ // Gets whether the menu is currently popped up
+ //
+ // Return value: %true if the menu is currently popped up
+ isActive: function() {
+ return this._menu.visible;
+ }
+};
+Signals.addSignalMethods(StatusMenu.prototype);
+++ /dev/null
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-/* Adapted from gdm/gui/user-switch-applet/applet.c */
-/*
- *
- * Copyright (C) 2004-2005 James M. Cape <jcape@ignore-your.tv>.
- * Copyright (C) 2008,2009 Red Hat, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "shell-status-menu.h"
-
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-
-#include <glib/gi18n-lib.h>
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-
-#include <gconf/gconf.h>
-#include <gconf/gconf-client.h>
-
-#include <dbus/dbus-glib.h>
-
-#define GDMUSER_I_KNOW_THIS_IS_UNSTABLE
-#include <gdmuser/gdm-user-manager.h>
-
-#include "shell-global.h"
-#include "shell-gconf.h"
-
-#define LOCKDOWN_DIR "/desktop/gnome/lockdown"
-#define LOCKDOWN_KEY LOCKDOWN_DIR "/disable_user_switching"
-
-#define SIDEBAR_VISIBLE_KEY SHELL_GCONF_DIR "/sidebar/visible"
-
-struct _ShellStatusMenuPrivate {
- GConfClient *client;
- GdmUserManager *manager;
- GdmUser *user;
-
- ClutterTexture *user_icon;
- BigBox *name_box;
- ClutterText *name;
-
- GtkWidget *menu;
- GtkWidget *account_item;
- GtkWidget *sidebar_item;
- GtkWidget *control_panel_item;
- GtkWidget *lock_screen_item;
- GtkWidget *login_screen_item;
- GtkWidget *quit_session_item;
- GtkWidget *shut_down_item;
-
- guint client_notify_lockdown_id;
-
- guint current_status_state;
-
- guint user_icon_changed_id;
- guint user_notify_id;
-
- gboolean has_other_users;
-
- GtkIconSize icon_size;
- guint pixel_size;
-};
-
-enum {
- PROP_0
-};
-
-G_DEFINE_TYPE(ShellStatusMenu, shell_status_menu, BIG_TYPE_BOX);
-
-/* Signals */
-enum
-{
- DEACTIVATED,
- LAST_SIGNAL
-};
-
-static guint shell_status_menu_signals [LAST_SIGNAL] = { 0 };
-
-static void
-reset_icon (ShellStatusMenu *status)
-{
- ShellStatusMenuPrivate *priv = status->priv;
- GdkPixbuf *pixbuf;
-
- if (priv->user == NULL)
- return;
-
- if (priv->user_icon != NULL)
- {
- pixbuf = gdm_user_render_icon (priv->user, 24);
-
- if (pixbuf == NULL)
- return;
-
- shell_clutter_texture_set_from_pixbuf (priv->user_icon, pixbuf);
-
- g_object_unref (pixbuf);
- }
-}
-
-static void
-update_name_text (ShellStatusMenu *status)
-{
- ShellStatusMenuPrivate *priv = status->priv;
-
- clutter_text_set_text (priv->name,
- gdm_user_get_real_name (GDM_USER (priv->user)));
-}
-
-static void
-on_user_icon_changed (GdmUser *user,
- ShellStatusMenu *status)
-{
- g_debug ("User icon changed");
- reset_icon (status);
-}
-
-static void
-user_notify_display_name_cb (GObject *object,
- GParamSpec *pspec,
- ShellStatusMenu *status)
-{
- update_name_text (status);
-}
-
-static void
-setup_current_user (ShellStatusMenu *status)
-{
- ShellStatusMenuPrivate *priv = status->priv;
- const char *name;
-
- priv->user = gdm_user_manager_get_user_by_uid (priv->manager, getuid ());
- if (priv->user != NULL)
- {
- g_object_ref (priv->user);
- name = gdm_user_get_real_name (priv->user);
- }
- else
- {
- name = _("Unknown");
- }
-
- update_name_text (status);
-
- if (priv->user != NULL)
- {
- reset_icon (status);
-
- priv->user_icon_changed_id =
- g_signal_connect (priv->user,
- "icon-changed",
- G_CALLBACK (on_user_icon_changed),
- status);
- priv->user_notify_id =
- g_signal_connect (priv->user,
- "notify::display-name",
- G_CALLBACK (user_notify_display_name_cb),
- status);
- }
-}
-
-static void
-maybe_lock_screen (ShellStatusMenu *status)
-{
- char *args[3];
- GError *err;
- GdkScreen *screen;
- gboolean use_gscreensaver = TRUE;
- gboolean res;
-
- g_debug ("Attempting to lock screen");
-
- args[0] = g_find_program_in_path ("gnome-screensaver-command");
- if (args[0] == NULL)
- {
- args[0] = g_find_program_in_path ("xscreensaver-command");
- use_gscreensaver = FALSE;
- }
-
- if (args[0] == NULL)
- return;
-
- if (use_gscreensaver)
- args[1] = "--lock";
- else
- args[1] = "-lock";
- args[2] = NULL;
-
- screen = gdk_screen_get_default ();
-
- err = NULL;
- res = gdk_spawn_on_screen (screen, g_get_home_dir (), args, NULL, 0, NULL,
- NULL, NULL, &err);
- if (!res)
- {
- g_warning (_("Can't lock screen: %s"), err->message);
- g_error_free (err);
- }
-
- if (use_gscreensaver)
- args[1] = "--throttle";
- else
- args[1] = "-throttle";
-
- err = NULL;
- res = gdk_spawn_on_screen (screen, g_get_home_dir (), args, NULL,
- (G_SPAWN_STDERR_TO_DEV_NULL | G_SPAWN_STDOUT_TO_DEV_NULL), NULL, NULL,
- NULL, &err);
- if (!res)
- {
- g_warning (_("Can't temporarily set screensaver to blank screen: %s"),
- err->message);
- g_error_free (err);
- }
-
- g_free (args[0]);
-}
-
-static void
-on_lock_screen_activate (GtkMenuItem *item,
- ShellStatusMenu *status)
-{
- maybe_lock_screen (status);
-}
-
-static void
-do_switch (ShellStatusMenu *status,
- GdmUser *user)
-{
- ShellStatusMenuPrivate *priv = status->priv;
- guint num_sessions;
-
- g_debug ("Do user switch");
-
- if (user == NULL)
- {
- gdm_user_manager_goto_login_session (priv->manager);
- goto out;
- }
-
- num_sessions = gdm_user_get_num_sessions (user);
- if (num_sessions > 0)
- gdm_user_manager_activate_user_session (priv->manager, user);
- else
- gdm_user_manager_goto_login_session (priv->manager);
-out:
- maybe_lock_screen (status);
-}
-
-static void
-on_login_screen_activate (GtkMenuItem *item,
- ShellStatusMenu *status)
-{
- GdmUser *user;
-
- user = NULL;
-
- do_switch (status, user);
-}
-
-static void
-spawn_external (ShellStatusMenu *status, const char *program)
-{
- char *args[2];
- GError *error;
- GdkScreen *screen;
- gboolean res;
-
- args[0] = g_find_program_in_path (program);
- if (args[0] == NULL)
- return;
- args[1] = NULL;
-
- screen = gdk_screen_get_default ();
-
- error = NULL;
- res = gdk_spawn_on_screen (screen, g_get_home_dir (), args, NULL, 0, NULL,
- NULL, NULL, &error);
- if (!res)
- {
- g_warning ("Failed to exec %s: %s", program, error->message);
- g_clear_error (&error);
- }
-
- g_free (args[0]);
-
-}
-
-static void
-on_control_panel_activate (GtkMenuItem *item,
- ShellStatusMenu *status)
-{
- spawn_external (status, "gnome-control-center");
-}
-
-static void
-on_account_activate (GtkMenuItem *item,
- ShellStatusMenu *status)
-{
- spawn_external (status, "gnome-about-me");
-}
-
-static void
-on_sidebar_toggled (GtkCheckMenuItem *item,
- ShellStatusMenu *status)
-{
- gconf_client_set_bool (status->priv->client, SIDEBAR_VISIBLE_KEY,
- gtk_check_menu_item_get_active (item), NULL);
-}
-
-
-/* Calls 'gnome-session-save arg' */
-static void
-gnome_session_save_command (const char *arg)
-{
- char *args[3];
- GError *error;
- GdkScreen *screen;
- gboolean res;
-
- args[0] = g_find_program_in_path ("gnome-session-save");
- if (args[0] == NULL)
- return;
-
- args[1] = (char *)arg;
- args[2] = NULL;
-
- screen = gdk_screen_get_default ();
-
- error = NULL;
- res = gdk_spawn_on_screen (screen, g_get_home_dir (), args, NULL, 0, NULL,
- NULL, NULL, &error);
- if (!res)
- {
- g_warning (_("Can't logout: %s"), error->message);
- g_error_free (error);
- }
-
- g_free (args[0]);
-}
-
-
-static void
-on_quit_session_activate (GtkMenuItem *item,
- ShellStatusMenu *status)
-{
- gnome_session_save_command ("--logout-dialog");
-}
-
-static void
-on_shut_down_activate (GtkMenuItem *item,
- ShellStatusMenu *status)
-{
- gnome_session_save_command ("--shutdown-dialog");
-}
-
-static void
-update_switch_user (ShellStatusMenu *status)
-{
- ShellStatusMenuPrivate *priv = status->priv;
- GSList *users;
-
- users = gdm_user_manager_list_users (priv->manager);
- priv->has_other_users = FALSE;
- if (users != NULL)
- priv->has_other_users = g_slist_length (users) > 1;
- g_slist_free (users);
-
- if (priv->has_other_users)
- gtk_widget_show (priv->login_screen_item);
- else
- gtk_widget_hide (priv->login_screen_item);
-}
-
-static void
-on_manager_user_added (GdmUserManager *manager,
- GdmUser *user,
- ShellStatusMenu *status)
-{
- update_switch_user (status);
-}
-
-static void
-on_manager_user_removed (GdmUserManager *manager,
- GdmUser *user,
- ShellStatusMenu *status)
-{
- update_switch_user (status);
-}
-
-static void
-on_manager_users_loaded (GdmUserManager *manager,
- ShellStatusMenu *status)
-{
- update_switch_user (status);
-}
-
-static void
-menu_style_set_cb (GtkWidget *menu, GtkStyle *old_style,
- ShellStatusMenu *status)
-{
- ShellStatusMenuPrivate *priv = status->priv;
- GtkSettings *settings;
- int width;
- int height;
-
- priv->icon_size = gtk_icon_size_from_name ("panel-menu");
- if (priv->icon_size == GTK_ICON_SIZE_INVALID)
- priv->icon_size = gtk_icon_size_register ("panel-menu", 24, 24);
-
- if (gtk_widget_has_screen (menu))
- settings = gtk_settings_get_for_screen (gtk_widget_get_screen (menu));
- else
- settings = gtk_settings_get_default ();
-
- if (!gtk_icon_size_lookup_for_settings (settings, priv->icon_size, &width,
- &height))
- priv->pixel_size = -1;
- else
- priv->pixel_size = MAX(width, height);
-}
-
-static void
-menuitem_style_set_cb (GtkWidget *menuitem,
- GtkStyle *old_style,
- ShellStatusMenu *status)
-{
- GtkWidget *image;
- const char *icon_name;
- ShellStatusMenuPrivate *priv = status->priv;
-
- if (menuitem == priv->login_screen_item)
- icon_name = "system-users";
- else if (menuitem == priv->lock_screen_item)
- icon_name = "system-lock-screen";
- else if (menuitem == priv->quit_session_item)
- icon_name = "system-log-out";
- else if (menuitem == priv->account_item)
- icon_name = "user-info";
- else if (menuitem == priv->control_panel_item)
- icon_name = "preferences-desktop";
- else if (menuitem == priv->shut_down_item)
- icon_name = "system-shutdown";
- else
- icon_name = GTK_STOCK_MISSING_IMAGE;
-
- image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (menuitem));
- gtk_image_set_pixel_size (GTK_IMAGE (image), priv->pixel_size);
- gtk_image_set_from_icon_name (GTK_IMAGE (image), icon_name, priv->icon_size);
-}
-
-static void
-on_deactivate (GtkMenuShell *menushell, gpointer user_data)
-{
- ShellStatusMenu *status = SHELL_STATUS_MENU (user_data);
- g_signal_emit (G_OBJECT (status), shell_status_menu_signals[DEACTIVATED], 0);
-}
-
-static void
-create_sub_menu (ShellStatusMenu *status)
-{
- ShellStatusMenuPrivate *priv = status->priv;
- GtkWidget *item;
-
- priv->menu = gtk_menu_new ();
- g_signal_connect (priv->menu, "style-set", G_CALLBACK (menu_style_set_cb),
- status);
-
- g_signal_connect (priv->manager, "users-loaded",
- G_CALLBACK (on_manager_users_loaded), status);
- g_signal_connect (priv->manager, "user-added",
- G_CALLBACK (on_manager_user_added), status);
- g_signal_connect (priv->manager, "user-removed",
- G_CALLBACK (on_manager_user_removed), status);
-
- priv->account_item = gtk_image_menu_item_new_with_label (_("Account Information..."));
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (priv->account_item),
- gtk_image_new ());
- gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), priv->account_item);
- g_signal_connect (priv->account_item, "style-set",
- G_CALLBACK (menuitem_style_set_cb), status);
- g_signal_connect (priv->account_item, "activate",
- G_CALLBACK (on_account_activate), status);
- gtk_widget_show (priv->account_item);
-
- priv->sidebar_item = gtk_check_menu_item_new_with_label (_("Sidebar"));
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (priv->sidebar_item),
- gconf_client_get_bool (priv->client, SIDEBAR_VISIBLE_KEY, NULL));
- gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), priv->sidebar_item);
- g_signal_connect (priv->sidebar_item, "toggled",
- G_CALLBACK (on_sidebar_toggled), status);
- gtk_widget_show (priv->sidebar_item);
-
- priv->control_panel_item = gtk_image_menu_item_new_with_label (_("System Preferences..."));
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (priv->control_panel_item),
- gtk_image_new ());
- gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), priv->control_panel_item);
- g_signal_connect (priv->control_panel_item, "style-set",
- G_CALLBACK (menuitem_style_set_cb), status);
- g_signal_connect (priv->control_panel_item, "activate",
- G_CALLBACK (on_control_panel_activate), status);
- gtk_widget_show (priv->control_panel_item);
-
- item = gtk_separator_menu_item_new ();
- gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), item);
- gtk_widget_show (item);
-
- priv->lock_screen_item
- = gtk_image_menu_item_new_with_label (_("Lock Screen"));
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (priv->lock_screen_item),
- gtk_image_new ());
- gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), priv->lock_screen_item);
- g_signal_connect (priv->lock_screen_item, "style-set",
- G_CALLBACK (menuitem_style_set_cb), status);
- g_signal_connect (priv->lock_screen_item, "activate",
- G_CALLBACK (on_lock_screen_activate), status);
- gtk_widget_show (priv->lock_screen_item);
-
- priv->login_screen_item = gtk_image_menu_item_new_with_label (_("Switch User"));
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (priv->login_screen_item),
- gtk_image_new ());
- gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), priv->login_screen_item);
- g_signal_connect (priv->login_screen_item, "style-set",
- G_CALLBACK (menuitem_style_set_cb), status);
- g_signal_connect (priv->login_screen_item, "activate",
- G_CALLBACK (on_login_screen_activate), status);
- /* Only show switch user if there are other users */
-
- /* Log Out */
- priv->quit_session_item = gtk_image_menu_item_new_with_label (_("Log Out..."));
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (priv->quit_session_item),
- gtk_image_new ());
- gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), priv->quit_session_item);
- g_signal_connect (priv->quit_session_item, "style-set",
- G_CALLBACK (menuitem_style_set_cb), status);
- g_signal_connect (priv->quit_session_item, "activate",
- G_CALLBACK (on_quit_session_activate), status);
- gtk_widget_show (priv->quit_session_item);
-
- /* Shut down */
- priv->shut_down_item = gtk_image_menu_item_new_with_label (_("Shut Down..."));
- gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (priv->shut_down_item),
- gtk_image_new ());
- gtk_menu_shell_append (GTK_MENU_SHELL (priv->menu), priv->shut_down_item);
- g_signal_connect (priv->shut_down_item, "style-set",
- G_CALLBACK (menuitem_style_set_cb), status);
- g_signal_connect (priv->shut_down_item, "activate",
- G_CALLBACK (on_shut_down_activate), status);
- gtk_widget_show (priv->shut_down_item);
-
- g_signal_connect (G_OBJECT (priv->menu), "deactivate",
- G_CALLBACK (on_deactivate), status);
-}
-
-static void
-shell_status_menu_init (ShellStatusMenu *status)
-{
- ShellStatusMenuPrivate *priv;
-
- status->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (status, SHELL_TYPE_STATUS_MENU,
- ShellStatusMenuPrivate);
-
- g_object_set (G_OBJECT (status),
- "orientation", BIG_BOX_ORIENTATION_HORIZONTAL,
- NULL);
- priv->client = gconf_client_get_default ();
-
- priv->user_icon = CLUTTER_TEXTURE (clutter_texture_new ());
- big_box_append (BIG_BOX (status), CLUTTER_ACTOR (status->priv->user_icon), 0);
-
- priv->name_box = BIG_BOX (big_box_new (BIG_BOX_ORIENTATION_VERTICAL));
- g_object_set (G_OBJECT (priv->name_box), "y-align", BIG_BOX_ALIGNMENT_CENTER, NULL);
- big_box_append (BIG_BOX (status), CLUTTER_ACTOR (priv->name_box), BIG_BOX_PACK_EXPAND);
- priv->name = CLUTTER_TEXT (clutter_text_new ());
- big_box_append (BIG_BOX (priv->name_box), CLUTTER_ACTOR (priv->name), BIG_BOX_PACK_EXPAND);
-
- priv->manager = gdm_user_manager_ref_default ();
- setup_current_user (status);
-
- create_sub_menu (status);
-}
-
-static void
-shell_status_menu_finalize (GObject *object)
-{
- ShellStatusMenu *status = SHELL_STATUS_MENU (object);
- ShellStatusMenuPrivate *priv = status->priv;
-
- gconf_client_notify_remove (priv->client, priv->client_notify_lockdown_id);
-
- g_signal_handler_disconnect (priv->user, priv->user_notify_id);
- g_signal_handler_disconnect (priv->user, priv->user_icon_changed_id);
-
- if (priv->user != NULL) {
- g_object_unref (priv->user);
- }
- g_object_unref (priv->client);
- g_object_unref (priv->manager);
-
- G_OBJECT_CLASS (shell_status_menu_parent_class)->finalize (object);
-}
-
-static void
-shell_status_menu_class_init (ShellStatusMenuClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (ShellStatusMenuPrivate));
-
- gobject_class->finalize = shell_status_menu_finalize;
-
- shell_status_menu_signals[DEACTIVATED] =
- g_signal_new ("deactivated",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (ShellStatusMenuClass, deactivated),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-}
-
-static void
-position_menu (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data)
-{
- ShellStatusMenu *status = SHELL_STATUS_MENU (user_data);
- ClutterActor *parent;
- float src_x, src_y;
- float width, height;
- int menu_width;
-
- gtk_widget_get_size_request (GTK_WIDGET (menu), &menu_width, NULL);
-
- /* Encapsulation breakage: it looks better if the menu is
- * aligned with the bottom of the actor's grandparent - the
- * panel, rather than with the bottom of the actor. We just
- * assume what the hierarchy is and where we are positioned
- * in the panel.
- */
- parent = clutter_actor_get_parent (CLUTTER_ACTOR (status));
- parent = clutter_actor_get_parent (parent);
- clutter_actor_get_transformed_position (parent, &src_x, &src_y);
- clutter_actor_get_transformed_size (parent, &width, &height);
- *x = (gint)(0.5 + src_x + width - menu_width);
- *y = (gint)(0.5 + src_y + height);
-}
-
-/**
- * shell_status_menu_toggle:
- * @menu: a #ShellStatusMenu
- *
- * If the menu is not currently up, pops it up. Otherwise, hides it.
- * Popping up may fail if another grab is already active; check with
- * shell_status_menu_is_active().
- */
-void
-shell_status_menu_toggle (ShellStatusMenu *status, ClutterEvent *event)
-{
- ShellStatusMenuPrivate *priv = status->priv;
-
- if (GTK_WIDGET_VISIBLE (priv->menu))
- {
- gtk_menu_popdown (GTK_MENU (priv->menu));
- }
- else
- {
- /* We don't want to overgrab a Mutter grab with the grab that GTK+
- * uses on menus.
- */
- ShellGlobal *global = shell_global_get ();
- if (shell_global_display_is_grabbed (global))
- return;
-
- gtk_menu_popup (GTK_MENU (priv->menu), NULL, NULL, position_menu,
- status, 1, event->button.time);
- }
-}
-
-/**
- * shell_status_menu_is_active:
- * @menu: a #ShellStatusMenu
- *
- * Gets whether the menu is currently popped up
- *
- * Return value: %TRUE if the menu is currently popped up
- */
-gboolean
-shell_status_menu_is_active (ShellStatusMenu *status)
-{
- ShellStatusMenuPrivate *priv = status->priv;
-
- return GTK_WIDGET_VISIBLE (priv->menu);
-}
-
-/**
- * shell_status_menu_get_name:
- * @menu: a #ShellStatusMenu
- *
- * Return value: (transfer none): the #ClutterText actor with the user's name.
- */
-ClutterText *
-shell_status_menu_get_name (ShellStatusMenu *menu)
-{
- return menu->priv->name;
-}
-
-/**
- * shell_status_menu_get_icon:
- * @menu: a #ShellStatusMenu
- *
- * Return value: (transfer none): the #ClutterTexture actor with the user icon.
- */
-ClutterTexture *
-shell_status_menu_get_icon (ShellStatusMenu *menu)
-{
- return menu->priv->user_icon;
-}